
#include <assert.h>
#include <math.h>

#include "assembler_parser.h"
#include "interpreter_facade_test.h"

using assembler::InterpreterFacade;
using assembler::MachineState;

namespace assembler_test {

void InterpreterFacadeTest::Test() {
  assert(fabs(FancyComputeZero(0.0)) < 1e-10);
  assert(fabs(FancyComputeZero(1.0)) < 1e-10);
  assert(fabs(FancyComputeZero(-2.0)) < 1e-10);

  double x = 0.0;
  double y = ComputeExpression1(x);
  assert(fabs(y - sin(1.0 / (x * x + 1))) < 1e-10);

  x = 1.0;
  y = ComputeExpression1(x);
  assert(fabs(y - sin(1.0 / (x * x + 1))) < 1e-10);
}

double InterpreterFacadeTest::ComputeExpression1(double x) {
  const char *commands =
    "MOV F1, F0\n"
    "MULT F1, F1\n"
    "ADD F1, 1.000\n"
    "MOV F0, 1.0000\n"
    "DIV F0, F1\n"
    "CALL @sin";

  MachineState state;
  state.set_reg(0, x);
  InterpreterFacade::ParseAndInterpret(&state, commands);
  
  return state.reg(0);
}

double InterpreterFacadeTest::FancyComputeZero(double x) {
  const char *commands =
    "PUSH F0\n"
    "CALL @sin\n"
    "MULT F0, F0\n"
    "MOV F1, F0\n"
    "POP F0\n"
    "CALL @cos\n"
    "MULT F0, F0\n"
    "ADD F0, F1\n"
    "SUB F0, 1.000";
  MachineState state;
  state.set_reg(0, x);
  
  InterpreterFacade::ParseAndInterpret(&state, commands);

  return state.reg(0);
}

}  // namespace assembler_test